/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Implementation of class CTaskCtrlData
 * \author Antti Maula <antti.maula@tkk.fi>, Marek Matusiak
 *
 * $Id: TaskCtrlData.cpp,v 1.21 2009-12-18 13:00:11 mmatusia Exp $
 *
 */
#include "TaskCtrlData.hpp"
#include "owndebug.h"

//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
using namespace MaCI::TaskCtrl;
//*****************************************************************************
OWNDEBUG_INITIALIZE_MODULENUMBER(); // Initialize module print capability
//*****************************************************************************

CTaskCtrlData::CTaskCtrlData()
  : CMaCIData(),
    iTimestampPtr(NULL),
    iCommandPtr(NULL),
    iTaskCtrlStatusEventPtr(NULL),
    iTaskCtrlTaskStatePtr(NULL),
    iTaskCtrlStateCommandPtr(NULL),
    iTaskCtrlRewardPtr(NULL),
    iTaskCtrlContractPtr(NULL),
    iErrorStringPtr(NULL),
    iTaskCtrlXMLPtrArray(),
    iTaskCtrlEvaluationPtrArray(),
    iTaskCtrlContractPtrArray(),
    iTaskCtrlStatePtrArray()
{
  SetLastElementType(KTypeUnknown);
  
}
//*****************************************************************************

CTaskCtrlData::~CTaskCtrlData()
{
  // Do any cleanups here.
}
//*****************************************************************************

CTaskCtrlData::CTaskCtrlData(const CTaskCtrlData &aData)
  : iTimestampPtr(NULL),
    iCommandPtr(NULL),
    iTaskCtrlStatusEventPtr(NULL),
    iTaskCtrlTaskStatePtr(NULL),
    iTaskCtrlStateCommandPtr(NULL),
    iTaskCtrlRewardPtr(NULL),
    iTaskCtrlContractPtr(NULL),
    iErrorStringPtr(NULL),
    iTaskCtrlXMLPtrArray(),
    iTaskCtrlEvaluationPtrArray(),
    iTaskCtrlContractPtrArray(),
    iTaskCtrlStatePtrArray()
{
  // Call assignment operator.
  *this = aData;
}
//*****************************************************************************

CTaskCtrlData &CTaskCtrlData::operator=(const CTaskCtrlData &aData)
{
  // Reset
  Reset();

  // Create an internal BinBag instance
  if (CreateInternalBinBag(aData.iBinBagContainer) == false) {
    dPrint(4,"WARNING: Failed to create internal binbag for object %p from object %p",
           this, &aData);
  }
  
  // Do the decode on the buffer; it sets pointers and ... stuff :)
  if (DecodeFrom(NULL) == false) {
    dPrint(4,"Warning: Failed to Decode CTaskCtrlData even though assignment operator used?");
  }
  
  return *this; 
}
//*****************************************************************************

bool CTaskCtrlData::DecodeFrom(gim::binbag::CBinBag *aBinBag)
{
  bool result = true;
  const gim::binbag::TBinBlob *b = NULL;
  int previous_type = -1;
  
  // Store pointer and test it for NullNess. only overwrite if the
  // argument was non-NULL.
  if (aBinBag != NULL) 
    SetBinBagContainerPtr(aBinBag);

  // Parse
  if (iBinBagContainer && iBinBagContainer->Rewind()) {
    while( (b = iBinBagContainer->GetNextBinary()) && result ) {
      switch(b->type) {

      case KTypeTimestamp: {
        if (iTimestampPtr == NULL && 
                  b->size == sizeof(Common::TTimestamp)) {
          iTimestampPtr = reinterpret_cast<const Common::TTimestamp *>(b->data);
                
        } else result = false;
        break;
      }
      
      case KTypeCommand: {
        if (iCommandPtr == NULL && 
            b->size == sizeof(TCommand)) {
          iCommandPtr = reinterpret_cast<const TCommand *>(b->data); 

        } else result = false;
        break;
      }
      
      case KTypeEvaluation: {
        if (b->size == sizeof(TTaskCtrlEvaluation)) {
          iTaskCtrlEvaluationPtrArray.push_back(reinterpret_cast<const TTaskCtrlEvaluation *>(b->data));           
        } else result = false;
        break;
      }
      
      case KTypeTaskState: {
        if (b->size == sizeof(TTaskCtrlTaskState)) {
          iTaskCtrlStatePtrArray.push_back(reinterpret_cast<const TTaskCtrlTaskState *>(b->data)); 
          //iTaskCtrlTaskStatePtr
        } else result = false;
        break;
      }    
      
      case KTypeStatusEvent: {
        if (iTaskCtrlStatusEventPtr == NULL && 
            b->size == sizeof(TTaskCtrlStatusEvent)) {
          iTaskCtrlStatusEventPtr = reinterpret_cast<const TTaskCtrlStatusEvent *>(b->data); 

        } else result = false;
        break;
      }    
        
      case KTypeStateCommand: {
        if (iTaskCtrlStateCommandPtr == NULL && 
            b->size == sizeof(TTaskCtrlStateCommand)) {
          iTaskCtrlStateCommandPtr = reinterpret_cast<const TTaskCtrlStateCommand *>(b->data); 
        } else result = false;
        break;
      }        
            
      case KTypeReward: {
        if (iTaskCtrlRewardPtr == NULL && 
            b->size == sizeof(TTaskCtrlReward)) {
          iTaskCtrlRewardPtr = reinterpret_cast<const TTaskCtrlReward *>(b->data); 
        } else result = false;
        break;
      }
        
        
      case KTypeContract: {
        if (b->size == sizeof(TTaskCtrlContract)) {
          iTaskCtrlContractPtrArray.push_back(reinterpret_cast<const TTaskCtrlContract *>(b->data));           
        } else result = false;
        break;
      }
       case KTypeErrorString: {
        if (iErrorStringPtr == NULL && 
            b->size >= sizeof(TErrorString)) {
          iErrorStringPtr = reinterpret_cast<const TErrorString *>(b->data); 
          // dPrint(1,"Decoding error string, '%s'",iErrorStringPtr->GetText().c_str());
          
        } else result = false;
        break;
       }
      case KTypeTaskCtrlXML: {
        if (b->size >= sizeof(TTaskCtrlXML)) {
          iTaskCtrlXMLPtrArray.push_back(reinterpret_cast<const TTaskCtrlXML *>(b->data)); 
        } 
        else  {
            result = false;
        }
        // Check size validity (required on variable size fields)
        if ((iTaskCtrlXMLPtrArray.back()->length + sizeof(TTaskCtrlXML) != b->size)) {
            iTaskCtrlXMLPtrArray.pop_back();
            result = false;
        }
        break;
      }
      

      default:
    // Unknown Type in BinBag. Do nothing.
    dPrint(10,"Unknown type %u, ignoring.", b->type);
        break;
      }
      
      // Store previous type
      previous_type = b->type;
    }
  } else result = false;

  // Store the result
  SetReadOnlyContainer(result);

  return result;
}
//*****************************************************************************

void CTaskCtrlData::Reset()
{
  // Call base class reset.
  CMaCIData::Reset();
  
  // Clean out. (Same values as in default constructor)
  iTimestampPtr = NULL;
  iCommandPtr = NULL;
  iTaskCtrlStatusEventPtr = NULL;
  //  iTaskCtrlTaskStatePtr = NULL;
  iTaskCtrlStateCommandPtr = NULL;
  iTaskCtrlRewardPtr = NULL;
  iTaskCtrlContractPtr = NULL;
  iErrorStringPtr = NULL;
  iTaskCtrlXMLPtrArray.clear();
  iTaskCtrlEvaluationPtrArray.clear();
  iTaskCtrlContractPtrArray.clear();
  iTaskCtrlStatePtrArray.clear();
  //iTaskCtrlTaskPtrArray.clear();
  //iTaskCtrlContractedTaskPtrArray.clear();
  SetLastElementType(KTypeUnknown);
  
}
//*****************************************************************************

void CTaskCtrlData::Print(const int l) const
{
    const gim::binbag::TBinBlob *b = NULL;
    // Parse
    if (iBinBagContainer && iBinBagContainer->Rewind()) {
        while( (b = iBinBagContainer->GetNextBinary())) {
            switch(b->type) {
                case KTypeTimestamp: {
                    const Common::TTimestamp *ts = 
                          reinterpret_cast<const Common::TTimestamp *>(b->data);
                    dPrint(l,"TTimestamp: s=%d, us=%d", 
                           ts->timestamp_s,
                           ts->timestamp_us);
                    break;
                }

                case KTypeCommand: {
                    const TCommand *ts = 
                    reinterpret_cast<const TCommand *>(b->data);
                    dPrint(l,"TCommand:: cmd = %d, flags = %u, TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u, commandID: %u",
                           ts->cmd, ts->flags, 
                  
                           ts->taskID.typeID0,
                           ts->taskID.typeID1,
                           ts->taskID.typeID2,
                           ts->taskID.typeID3,
                           ts->taskID.typeID4,
                           ts->taskID.typeID5,
                           ts->taskID.typeID6,
                           ts->taskID.host,
                           ts->taskID.owner,
                           ts->taskID.taskID,
                           ts->commandID);
                    break;
                }
                
                case KTypeEvaluation: {
                    const TTaskCtrlEvaluation *ev = 
                      reinterpret_cast<const TTaskCtrlEvaluation *>(b->data);
                    dPrint(l,"TTaskCtrlEvaluation:: TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u, validity = %u, value = %.2f, ETC_ms = %u",
                           ev->taskID.typeID0,
                           ev->taskID.typeID1,
                           ev->taskID.typeID2,
                           ev->taskID.typeID3,
                           ev->taskID.typeID4,
                           ev->taskID.typeID5,
                           ev->taskID.typeID6,
                           ev->taskID.host,
                           ev->taskID.owner,
                           ev->taskID.taskID,
                           ev->validity, ev->value, ev->ETC_ms);
                    break;
                }

                case KTypeTaskState: {
                    const TTaskCtrlTaskState *ae = 
                    reinterpret_cast<const TTaskCtrlTaskState *>(b->data);
                    dPrint(l,"TTaskCtrlTaskState:: TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u, taskState = %d, ETC_ms = %u, percentComplete = %.2f",
                           ae->taskID.typeID0,
                           ae->taskID.typeID1,
                           ae->taskID.typeID2,
                           ae->taskID.typeID3,
                           ae->taskID.typeID4,
                           ae->taskID.typeID5,
                           ae->taskID.typeID6,
                           ae->taskID.host,
                           ae->taskID.owner,
                           ae->taskID.taskID,
                           ae->taskState, ae->ETC_ms, ae->percentComplete);
                    break;
                }        

                case KTypeStatusEvent: {
                    const TTaskCtrlStatusEvent *ae = 
                    reinterpret_cast<const TTaskCtrlStatusEvent *>(b->data);
                    dPrint(l,"TTaskCtrlStatusEvent:: TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u, taskState = %d, ETC_ms = %u, percentComplete = %.2f",
                           ae->taskID.typeID0,
                           ae->taskID.typeID1,
                           ae->taskID.typeID2,
                           ae->taskID.typeID3,
                           ae->taskID.typeID4,
                           ae->taskID.typeID5,
                           ae->taskID.typeID6,
                           ae->taskID.host,
                           ae->taskID.owner,
                           ae->taskID.taskID,
                           ae->taskState, ae->ETC_ms, ae->percentComplete);
                    break;
                }           
                
                case KTypeStateCommand: {
                    const TTaskCtrlStateCommand *sc = 
                    reinterpret_cast<const TTaskCtrlStateCommand *>(b->data);
                    dPrint(l,"TTaskStateCommand:: cmd = %d",
                            sc->cmd);
                    break;
                }   
                
                case KTypeReward: {
                    const TTaskCtrlReward *sc = 
                    reinterpret_cast<const TTaskCtrlReward *>(b->data);
                    dPrint(l,"TTaskCtrlReward:: TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u, reward = %.2f",
                           sc->taskID.typeID0,
                           sc->taskID.typeID1,
                           sc->taskID.typeID2,
                           sc->taskID.typeID3,
                           sc->taskID.typeID4,
                           sc->taskID.typeID5,
                           sc->taskID.typeID6,
                           sc->taskID.host,
                           sc->taskID.owner,
                           sc->taskID.taskID,
                           sc->reward);
                    break;
                }         
                
            case KTypeContract: {
                    const TTaskCtrlContract *sc = 
                    reinterpret_cast<const TTaskCtrlContract *>(b->data);
                    dPrint(l,"TTaskCtrlContract:: TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u, reward = %.2f, dl_s = %u, dl_us = %u",
                           sc->taskID.typeID0,
                           sc->taskID.typeID1,
                           sc->taskID.typeID2,
                           sc->taskID.typeID3,
                           sc->taskID.typeID4,
                           sc->taskID.typeID5,
                           sc->taskID.typeID6,
                           sc->taskID.host,
                           sc->taskID.owner,
                           sc->taskID.taskID,
                           sc->reward, sc->deadline_s, sc->deadline_us);
                    break;
                }                 
            case KTypeErrorString:{
              const TErrorString *er = reinterpret_cast<const TErrorString *>(b->data);
              dPrint(l,"TErrorString: '%.1024s'",er->text);

              break;
            }
                case KTypeTaskCtrlXML: {
                    const TTaskCtrlXML *tcxml = 
                      reinterpret_cast<const TTaskCtrlXML *>(b->data);
                    dPrint(l,"TTaskCtrlXML: '%.1024s'", tcxml->text);
                    break;
                }

                default:
                // Unknown Type in BinBag. Do nothing.
                dPrint(10,"Unknown type %u, ignoring.", b->type);
                break;
            }
        }
    }
}
//*****************************************************************************

bool CTaskCtrlData::SetTimestamp(const Common::TTimestamp &aStamp)
{
  bool result = false;
  if (!IsReadOnlyContainer() && iTimestampPtr == NULL) {
    ADDELEMENT(Common::TTimestamp, KTypeTimestamp, iTimestampPtr, aStamp);
    result = true;
  }
  return result;
}
//*****************************************************************************

bool CTaskCtrlData::SetCommand(const TCommand &aCmd)
{  
  
  bool result = false;
  if (!IsReadOnlyContainer() && iCommandPtr == NULL) {
    ADDELEMENT(TCommand, KTypeCommand, 
               iCommandPtr, aCmd);
    result = true;
  }
  return result;
}
//*****************************************************************************

bool CTaskCtrlData::AddTaskCtrlEvaluation (const TTaskCtrlEvaluation &aEvaluation){  
  bool result = false;
  if (!IsReadOnlyContainer()) {
    const gim::binbag::TBinBlob *b = 
      iBinBagContainer->AddBinary(KTypeEvaluation, 
                                  (const char *)&aEvaluation, 
                                  sizeof(TTaskCtrlEvaluation));
    
    // Typecast
    const TTaskCtrlEvaluation *eval = reinterpret_cast<const TTaskCtrlEvaluation *>(b->data); 

    // Store.
    iTaskCtrlEvaluationPtrArray.push_back(eval);
    SetLastElementType(KTypeEvaluation);
    
    result = true;
  }
  return result;
}

//*****************************************************************************

bool CTaskCtrlData::AddTaskCtrlContract (const TTaskCtrlContract &aContract){  
  bool result = false;
  if (!IsReadOnlyContainer()) {
    const gim::binbag::TBinBlob *b = 
      iBinBagContainer->AddBinary(KTypeContract, 
                                  (const char *)&aContract, 
                                  sizeof(TTaskCtrlContract));
    
    // Typecast
    const TTaskCtrlContract *cont = reinterpret_cast<const TTaskCtrlContract *>(b->data); 

    // Store.
    iTaskCtrlContractPtrArray.push_back(cont);
    SetLastElementType(KTypeContract);
    
    result = true;
  }
  return result;
}

//*****************************************************************************

bool CTaskCtrlData::SetTaskCtrlStateCommand(const TTaskCtrlStateCommand &aTaskCtrlStateCommand) 
{  
  bool result = false;
  if (!IsReadOnlyContainer() && iTaskCtrlStateCommandPtr == NULL) {
    ADDELEMENT(TTaskCtrlStateCommand, KTypeStateCommand, 
               iTaskCtrlStateCommandPtr, aTaskCtrlStateCommand);
    result = true;
  }
  return result;
}

//*****************************************************************************

bool CTaskCtrlData::SetTaskCtrlReward(const TTaskCtrlReward &aTaskCtrlReward) 
{  
  bool result = false;
  if (!IsReadOnlyContainer() && iTaskCtrlRewardPtr == NULL) {
    ADDELEMENT(TTaskCtrlReward, KTypeReward, 
               iTaskCtrlRewardPtr, aTaskCtrlReward);
    result = true;
  }
  return result;
}
//*****************************************************************************
/*bool CTaskCtrlData::SetTaskCtrlContract(const TTaskCtrlContract &aTaskCtrlContract) 
{  
  bool result = false;
  if (!IsReadOnlyContainer() && iTaskCtrlContractPtr == NULL) {
    ADDELEMENT(TTaskCtrlContract, KTypeContract, 
               iTaskCtrlContractPtr, aTaskCtrlContract);
    result = true;
  }
  return result;
}*/
//*****************************************************************************
bool CTaskCtrlData::SetTaskCtrlTaskState(const TTaskCtrlStatusEvent &aState)
{  
  bool result = false;
  if (!IsReadOnlyContainer()) {
    const gim::binbag::TBinBlob *b = 
      iBinBagContainer->AddBinary(KTypeTaskState, 
                                   (const char *)&aState, 
                                   sizeof(TTaskCtrlTaskState));
    
    // Typecast
    const TTaskCtrlTaskState *stat = reinterpret_cast<const TTaskCtrlTaskState *>(b->data); 

    // Store.
    iTaskCtrlStatePtrArray.push_back(stat);
    SetLastElementType(KTypeTaskState);
    
    result = true;
  }
  return result;


}
//*****************************************************************************
bool CTaskCtrlData::SetTaskCtrlStatusEvent(const TTaskCtrlStatusEvent &aEvent)
{  
  bool result = false;
  if (!IsReadOnlyContainer() && iTaskCtrlStatusEventPtr == NULL) {
    ADDELEMENT(TTaskCtrlStatusEvent, KTypeStatusEvent, 
               iTaskCtrlStatusEventPtr, aEvent);
    result = true;
  }
  return result;
}

//*****************************************************************************

bool CTaskCtrlData::AddTaskCtrlXML(const TTaskCtrlXML &aXML)
{  
  bool result = false;
  if (!IsReadOnlyContainer()) {
    const gim::binbag::TBinBlob *b = 
      iBinBagContainer->AddBinary(KTypeTaskCtrlXML, 
                                  (const char *)&aXML, 
                                  aXML.GetContainerSize());
    // Typecast
    
    const TTaskCtrlXML *xml = reinterpret_cast<const TTaskCtrlXML *>(b->data); 
    // Store.
    iTaskCtrlXMLPtrArray.push_back(xml);
    SetLastElementType(KTypeTaskCtrlXML);
    
    result = true;
  }

  return result;
}
//*****************************************************************************

bool CTaskCtrlData::AddTaskCtrlXMLString(const std::string &aXmlString)
{
  bool result = false;
  uint8_t *ptr = NULL;
  unsigned int bytes = 0;

  // Create dynamic container from xmlString
  TTaskCtrlXML *tcxml = TTaskCtrlXML::CreateTextElement(&ptr, bytes, aXmlString);
  
  // Use the normal setter function. (use result)
  result = AddTaskCtrlXML(*tcxml);

  // Unconditionally destroy dynamic element.
  TTaskCtrlXML::DestroyTextElement(tcxml);

  return result;
}
//*****************************************************************************
   
bool CTaskCtrlData::AddErrorString(const MaCI::TaskCtrl::TErrorString &aErrorString)
{

  bool result = false;
  if (!IsReadOnlyContainer()) {
    const gim::binbag::TBinBlob *b = 
      iBinBagContainer->AddBinary(KTypeErrorString, 
                                  (const char *)&aErrorString, 
                                  aErrorString.GetContainerSize());
    // Typecast
    
    const TErrorString *err = reinterpret_cast<const TErrorString *>(b->data); 
    // Store.
    iErrorStringPtr = err;
    SetLastElementType(KTypeErrorString);
    
    result = true;
  }


  return result;

}
//*****************************************************************************

bool CTaskCtrlData::AddErrorString(const std::string &aErrorString)
{
  //  dPrint(1,"Adding error string '%s'",aErrorString.c_str());
  bool result = false;
  uint8_t *ptr = NULL;
  unsigned int bytes = 0;

  // Create dynamic container from xmlString
  TErrorString *terr = TErrorString::CreateTextElement(&ptr, bytes, aErrorString);
  //dPrint(1,"TErrorString '%s'",terr->GetText().c_str());
  // Use the normal setter function. (use result)
  result = AddErrorString(*terr);

  // Unconditionally destroy dynamic element.
  TTaskCtrlXML::DestroyTextElement(terr);
  return result;
}


//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************

const MaCI::Common::TTimestamp *CTaskCtrlData::GetTimestamp(void) const
{
  return iTimestampPtr;
}
//*****************************************************************************

const TCommand *CTaskCtrlData::GetCommand(void) const
{
  return iCommandPtr;
}
//*****************************************************************************
const TTaskCtrlEvaluationPtrArray &CTaskCtrlData::GetTaskCtrlEvaluationArray(void) const
{
  return iTaskCtrlEvaluationPtrArray;
}
//*****************************************************************************

const TTaskCtrlTaskState *CTaskCtrlData::GetTaskCtrlTaskState(void) const
{
  if(iTaskCtrlStatePtrArray.size() > 0){
    return iTaskCtrlStatePtrArray[0];
  }else{
    return NULL;
  }
}
//*****************************************************************************

const TTaskCtrlTaskStatePtrArray &CTaskCtrlData::GetTaskCtrlTaskStatePtrArray(void) const
{

  return iTaskCtrlStatePtrArray;

}
//*****************************************************************************
const TTaskCtrlStatusEvent *CTaskCtrlData::GetTaskCtrlStatusEvent(void) const
{
  return iTaskCtrlStatusEventPtr;
}
//*****************************************************************************

const TTaskCtrlStateCommand *CTaskCtrlData::GetTaskCtrlStateCommand(void) const
{
  return iTaskCtrlStateCommandPtr;
}
//*****************************************************************************
const TTaskCtrlReward *CTaskCtrlData::GetTaskCtrlReward(void) const
{
  return iTaskCtrlRewardPtr;
}
//*****************************************************************************
//*****************************************************************************
const TTaskCtrlContractPtrArray &CTaskCtrlData::GetTaskCtrlContractPtrArray(void) const
{
  return iTaskCtrlContractPtrArray;
}
//*****************************************************************************
const TTaskCtrlXMLPtrArray &CTaskCtrlData::GetTaskCtrlXMLPtrArray(void) const
{
  return iTaskCtrlXMLPtrArray;
}
//*****************************************************************************
std::string CTaskCtrlData::GetTaskCtrlXMLString(void) const
{
  std::string result;

  if (!iTaskCtrlXMLPtrArray.empty()) {
    result = iTaskCtrlXMLPtrArray.front()->GetText();
  }

  return result;
}
//*****************************************************************************

std::string CTaskCtrlData::GetTaskCtrlErrorString(void) const
{
 std::string result;

  if (iErrorStringPtr) {
    result = iErrorStringPtr->GetText();
  }

  return result;

}
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************

#ifdef COMPILE_TASKCTRLDATA_STANDALONE_MAIN
#include <string>

int main(void)
{
    using namespace MaCI::TaskCtrl;
    gim::binbag::CBinBag bb;
    CTaskCtrlData A;
    CTaskCtrlData B;
    bool r;

    printf("Carry out Encoding/Decoding test.\n");

    debugInit();
    debugSetGlobalDebugLvl(1);

    //////////////////////////////////////////////////////////
    ///////// Encode /////////////////////////////////////////
    //////////////////////////////////////////////////////////
    printf("\nEncoding...\n");
    // Do Encoding 
    A.EncodeTo(&bb);

    printf("Encode: Timestamp(1,2) ... ");
    r = A.SetTimestamp(MaCI::Common::TTimestamp(1, 2));
    assert(r == true);
    printf("OK.\n");

    printf("Encode: TCommand(KCommandAddTask, 0, 21, 1001) ... ");
    r = A.SetCommand(TCommand(KCommandAddTask, KCommandFlagDefault, TTaskCtrlTaskID(21,20,19,18)));
    assert(r == true);
    printf("OK.\n");

    printf("Encode: TaskCtrlXML; data='<foo>diibadaabadaa</foo>'");
    r = A.AddTaskCtrlXMLString("<foo>diibadaabadaa</foo>");
    assert(r == true);
    printf("OK.\n");
    
    printf("Encode: AddTaskCtrlEvaluation(TTaskCtrlEvaluation(124, 1, 233.90, 4000)");
    r= A.AddTaskCtrlEvaluation(TTaskCtrlEvaluation(TTaskCtrlTaskID(21,20,19,18), 1, 233.90));
    assert(r == true);
    printf("OK.\n");
    
    printf("Encode: AddTaskCtrlEvaluation(TTaskCtrlEvaluation(124, 0, 2237.7, 100000)");
    r= A.AddTaskCtrlEvaluation(TTaskCtrlEvaluation(TTaskCtrlTaskID(21,20,19,18), 0, 2237.7));
    assert(r == true);
    printf("OK.\n");

    printf("Encode: TTaskCtrlStateCommand(1)'");
    r = A.SetTaskCtrlStateCommand(KTaskStateCommandStart);
    assert(r == true);
    printf("OK.\n");

    printf("Encode: SetTaskCtrlStatusEvent(TTaskCtrlStatusEvent(100,KTaskStateCommandStart, 2200, 35.0))");
    r = A.SetTaskCtrlStatusEvent(TTaskCtrlStatusEvent(TTaskCtrlTaskID(100,99,98,97),KTaskStateStart, 2200, 35.0));
    assert(r == true);
    printf("OK.\n");
  
    uint8_t *ptr = NULL;
    unsigned int bytes = 23;
    TTaskCtrlXML *tcxml = TTaskCtrlXML::CreateTextElement(&ptr, bytes, "<foo>diibadaabadaa</foo>");
    dPrint(1, "tcxml: %s", tcxml->GetText().c_str());
    assert(tcxml != NULL);


    std::string error = "error";
    r = A.AddErrorString(error);
    assert(r == true);
    printf("OK.\n");

    A.Print(0);

    //////////////////////////////////////////////////////////
    ///////// Decode /////////////////////////////////////////
    //////////////////////////////////////////////////////////
    printf("\nDecoding...\n");
    // Do Decoding
    assert(B.DecodeFrom(&bb) == true);
    printf("Decode: GetTimestamp() = (%d, %d) ... ", 
     B.GetTimestamp()->timestamp_s, 
     B.GetTimestamp()->timestamp_us);
    assert(B.GetTimestamp()->timestamp_s == 1);
    assert(B.GetTimestamp()->timestamp_us == 2);
    printf("Assertions OK.\n");

    /*   printf("Decode: GetCommand() = (%d, %d, %u, %u, %u, %u) ... ", 
     B.GetCommand()->cmd, 
     B.GetCommand()->flags,
     B.GetCommand()->taskID.major0,
     B.GetCommand()->taskID.minor0,
     B.GetCommand()->taskID.minor1,
     B.GetCommand()->taskID.minor2);
    assert(B.GetCommand()->cmd == KCommandAddTask);
    assert(B.GetCommand()->flags == 0);
    assert(B.GetCommand()->taskID.major0 == 21);
    assert(B.GetCommand()->taskID.minor0 == 20);
    assert(B.GetCommand()->taskID.minor1 == 19);
    assert(B.GetCommand()->taskID.minor2 == 18);
    */
    printf("Assertions OK.\n");

    printf("Decode: GetTaskCtrlXMLString() = ('%s') ... \n", B.GetTaskCtrlXMLString().c_str());
    assert(B.GetTaskCtrlXMLString().c_str() == std::string("<foo>diibadaabadaa</foo>"));
    
    
    /*    for(EACH_IN_i(B.GetTaskCtrlEvaluationArray())) {
        printf("Decode: GetTaskCtrlEvaluationArray() = %u %u %u %u %u %.2f %u \n",
        (*i)->taskID.major0,
        (*i)->taskID.minor0,
        (*i)->taskID.minor1,
        (*i)->taskID.minor2,
        (*i)->validity,
        (*i)->value,
        (*i)->ETC_ms);         
    }
    
   
    printf("Decode: GetTaskCtrlStateCommand %d\n", B.GetTaskCtrlStateCommand()->cmd);
    assert( B.GetTaskCtrlStateCommand()->cmd==KTaskStateCommandStart);
    printf("Assertions OK.\n");


    printf("Decode: SetTaskCtrlStatusEvent %u %u %u %u %d %u %.2f\n",
            B.GetTaskCtrlStatusEvent()->taskID.major0,
            B.GetTaskCtrlStatusEvent()->taskID.minor0,
            B.GetTaskCtrlStatusEvent()->taskID.minor1,
            B.GetTaskCtrlStatusEvent()->taskID.minor2,
            B.GetTaskCtrlStatusEvent()->taskState,
            B.GetTaskCtrlStatusEvent()->ETC_ms,
            B.GetTaskCtrlStatusEvent()->percentComplete);
    assert(B.GetTaskCtrlStatusEvent()->taskID.major0 == 100);
    assert(B.GetTaskCtrlStatusEvent()->taskID.minor0 == 99);
    assert(B.GetTaskCtrlStatusEvent()->taskID.minor1 == 98);
    assert(B.GetTaskCtrlStatusEvent()->taskID.minor2 == 97);
    assert(B.GetTaskCtrlStatusEvent()->taskState==KTaskStateStart);
    assert(B.GetTaskCtrlStatusEvent()->ETC_ms==2200);
    assert(B.GetTaskCtrlStatusEvent()->percentComplete==35.0);
    printf("Assertions OK.\n");
    */
    printf("Decode: GetErrorString '%s'",B.GetTaskCtrlErrorString().c_str());
    printf("Test complete.\n");


}
#endif
//*****************************************************************************
//*****************************************************************************
